#ifndef CICORE_MATRIX_H
#define CICORE_MATRIX_H

#include <cmath>
#include <sstream>
#include <string>

#include "Core_GLOBAL.h"

namespace CICore {
    class Matrix {        

    public:        
        Matrix();                   //Default Constructor
        Matrix (Matrix& m);         //Constructor
        virtual ~Matrix ();         //Destructor

        float elements[16];         //Matrix's elements                    

        //Utility Methods
        float GetDeterminant3() const;                                          //Method called to compute and get the 3x3 matrix's determinant
        float GetDeterminant() const;                                           //Method called to compute and get the matrix's determinant
        Matrix GetSubMatrix (int i, int j) const;                               //Method called to get the submatrix i x j
        Matrix GetInverse() const;                                              //Method called to compute and get the matrix's inverse
        float GetValue (unsigned int row, unsigned int col) const;              //Method called to get the value identified by row and col

        void LoadIdentity();                                                    //Method called to make this matrix the identity matrix

        void SetValue (unsigned int row, unsigned int col, const float value);  //Method called to set the value identified by row and col

        void SetTranslation (const float* v);                                   //Method called to set the translation required
        void SetTranslation (const float x, const float y, const float z);      //Method called to set the translation required

        void SetRotationInRadians (const float* radians);                       //Method called to set the rotation required in radians
        void SetRotation (const float* degrees);                                //Method called to set the rotation required
        void SetRotation (const float x, const float y, const float z);         //Method called to set the rotation required

        void SetScaling (const float value);                                    //Method called to set the uniform scaling required
        void SetScaling (const float x, const float y, const float z);          //Method called to set the scaling required

        std::string ToString() const;                                           //Method called to represent the matrix in a string
    
        Matrix& operator = (const Matrix& m);            //Assignment 

    };    

    //Basic matrix's binary operations
    Matrix operator + (const Matrix& a, const Matrix& b);       //Sum between two matrices    

    Matrix operator - (const Matrix& a, const Matrix& b);       //Difference between two matrices    

    Matrix operator * (const Matrix& a, const Matrix& b);       //Product between two matrices
    Matrix& operator *= (Matrix& a, const Matrix& b);           //Assignment by multiplication between two matrices

}
#endif /* CICORE_MATRIX_H */
